﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinqDemo
{
    /// <summary>
    /// 扩展方法
    /// 静态方法
    /// 
    /// 操作：
    /// 把类变成静态类
    /// 把方法的第一个参数+ this修饰
    /// </summary>
    public static class MethodExtension
    {
        #region Linq需要用到的扩展方法
        /// <summary>
        /// 判断逻辑不一样--不一样的地方---其实可以做成一个方法---（一段逻辑），既然逻辑不一样，就可以把逻辑当做参数来传递；
        /// 把逻辑当做参数来传递------？？？？  委托    Student参数，返回bool类型的委托；
        /// func的传递的方法 是 IsOk01   IsOk02   IsOk03
        /// 
        /// 系统提供的Where 一个方法可以满足不同类型的需求：那就是泛型方法；
        /// 
        /// 
        /// 个人见解:从普通的循环判断到用委托解决
        /// </summary>
        /// <param name="studentList"></param>
        /// <returns></returns>
        public static List<Student> RichardWhere(this List<Student> studentList, Func<Student, bool> func)
        {
            //1.要求查询Student中年龄小于30的；  
            List<Student> studentReulstList = new List<Student>();
            foreach (Student std in studentList)
            {
                if (func(std))//每次都是对list里面的一个值做判断
                {
                    studentReulstList.Add(std);
                }
            }
            return studentReulstList;
        }

        /// <summary>
        /// 系统提供的Where 一个方法可以满足不同类型的需求：那就是泛型方法；
        /// 
        /// 就是系统提供的Where方法的底层实现；
        /// 统一获取
        /// 
        /// </summary>
        /// <param name="studentList"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static List<T> RichardWhereNew<T>(this List<T> studentList, Func<T, bool> func)
        {
            //1.要求查询Student中年龄小于30的；

            //判断之后，满足条件的对象存储到集合，最后统一返回；
            List<T> studentReulstList = new List<T>();
            foreach (T std in studentList)
            {
                if (func(std))
                {
                    Console.WriteLine("判断条件~~~ RichardWhereNew ");
                    studentReulstList.Add(std);
                }
            }
            return studentReulstList;
        }

        //Linq设计思想：
        //1.把相同的不变的业务逻辑统一封装好；
        //2.把可变的业务逻辑通过委托来进行传递；

        //where: 循环的内容封装----条件判断的内容（可变的）---通过委托来传递；
        //Group: 循环的内容封装----把可变的逻辑通过委托来传递；
        //框架的设计中：

        //访问数据库： 准备链接字符串，打开链接，准备Sql语句，执行语句；
        //LinqToSql  相同的逻辑（准备链接字符串，打开链接）统一封装，可变的逻辑（SQl的拼装--通过表达式目录树来传递）
        //LinqToXml  准备document对象，读取文件，Op文件（通用的逻辑）---统一封装， 查询条件委托传递；
        //LinqToRedis  
        //LinqToCache  
        //LinqToEveryThing  万物节课Linq：




        /// <summary>
        /// 按需要获取
        /// 
        /// 获取的结果会更加即时~~ 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="studentList"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static IEnumerable<T> RichardWhereNew001<T>(this List<T> studentList, Func<T, bool> func)
        {
            //1.要求查询Student中年龄小于30的；   
            ///迭代器----判断一次，就返回一次；
            foreach (T std in studentList)
            {
                if (func(std))
                {
                    Console.WriteLine("判断条件~~~ RichardWhereNew001 ");
                    yield return std;
                }
            }
        }
        #endregion

        /// <summary>
        /// 新类，写新方法
        /// </summary>
        public static void StudyEmbedded(this Student student)
        {
            Console.WriteLine($"{student.Id} {student.Name}跟着Richard师学习嵌入式开发");
        }


        /// <summary>
        /// 如果是查过10个长度的字符串，保留前面的10个字符，后面的内容是 .....
        /// 例如： 中华人名共和国万岁，习大大你
        ///        中华人名共和国万岁.....
        ///        
        /// 统一处理字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Sub(this string str, int len = 10)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return string.Empty;
            }

            if (str.Length <= 10)
            {
                return str;
            }
            else
            {
                str = $"{str.Substring(0, len)}....";
                return str;
            }

        }


        public static string SubObj(this object str, int len = 10)
        {
            if (str is null)
            {
                return string.Empty;
            }

            if (str.ToString().Length <= 10)
            {
                return str.ToString();
            }
            else
            {
                str = $"{str.ToString().Substring(0, len)}....";
                return str.ToString();
            }

        }

        public static string SubGeneric<T>(this T str, int len = 10) where T : class
        {
            if (str is null)
            {
                return string.Empty;
            }

            if (str.ToString().Length <= 10)
            {
                return str.ToString();
            }
            else
            {
                return $"{str.ToString().Substring(0, len)}....";
            }

        }
    }
}
